#include <cassert>
#include <climits>
#include <cstddef>
#include <cstdio>
#include <ctime>
#include <iostream>
#include "Multiplier.h"
#include "types.h"
#include <random>

int main() {
    std::mt19937 gen(time(NULL));
    std::uniform_int_distribution<UInt> distrib(0, UINT_UPPER);
    Multiplier m;
    m.reset();

    int N = 1000;

    int correct_count = 0;

    for (int i = 0; i < N; ++i) {
        UInt x = distrib(gen);
        UInt y = distrib(gen);
    
        auto [uu_a, uu_r] = m.UU(x, y);
        auto [us_a, us_r] = m.US(x, y);
        auto [su_a, su_r] = m.SU(x, y);
        auto [ss_a, ss_r] = m.SS(x, y);

        auto uu_wrong = uu_a != uu_r;
        auto us_wrong = us_a != us_r;
        auto su_wrong = su_a != su_r;
        auto ss_wrong = ss_a != ss_r;
        
        if (uu_wrong) {
            std::printf("Failed UU: result = %016lx, answer = %016lx\n", UInt(uu_r), UInt(uu_a));
        }
        if (us_wrong) {
            std::printf("Failed US: result = %016lx, answer = %016lx\n", UInt(us_r), UInt(us_a));
        }
        if (su_wrong) {
            std::printf("Failed SU: result = %016lx, answer = %016lx\n", UInt(su_r), UInt(su_a));
        }
        if (ss_wrong) {
            std::printf("Failed SS: result = %016lx, answer = %016lx\n", UInt(ss_r), UInt(ss_a));
        }
        if (!(uu_wrong || us_wrong || su_wrong || ss_wrong)) {
            correct_count++;
        }
    }
    
    std::printf("Correct Rate: %d/%d\n", correct_count, N);
    return 0;
}
